package gogoqiu.java.base;

import java.io.UnsupportedEncodingException;
import java.net.URLEncoder;
import java.nio.charset.StandardCharsets;
import java.text.DecimalFormat;
import java.util.Objects;

/**
 * 工具类集合，对应 TypeScript 中的 utils、Size 类及独立函数
 */
public class ToolUtils {

    // ======================== utils 类对应方法 ========================
    /**
     * 生成 myvlc 协议的 URL（对应 myvlc_encode）
     * @param url 原始URL
     * @return 编码后的 myvlc 协议URL
     * @throws UnsupportedEncodingException 
     */
    public static String myvlcEncode(String url) throws UnsupportedEncodingException {
        Objects.requireNonNull(url, "URL 不能为空");
        // 对应 TypeScript 的 escape 函数，Java 中使用 UTF-8 编码
        String encodedUrl = URLEncoder.encode(url, StandardCharsets.UTF_8.name());
        return "myvlc://play.com/" + encodedUrl;
    }

    // ======================== Size 类对应方法 ========================
    /**
     * 格式化比特大小（对应 getBitSizeFormat）
     * @param count 待格式化的数值字符串
     * @param step 格式化精度（g/m/k/b）
     * @return 格式化后的字符串
     */
    public static String getBitSizeFormat(String count, String step) {
        // 处理 step 默认值
        if (step == null || step.isEmpty()) {
            step = "k";
        }
        // 解析数值，处理非数字情况
        long countNum;
        try {
            countNum = Long.parseLong(count);
        } catch (NumberFormatException e) {
            throw new IllegalArgumentException("count 必须是有效的数字字符串", e);
        }

        final long G = 1024L * 1024 * 1024;
        final long M = 1024L * 1024;
        final long K = 1024L;
        StringBuilder sb = new StringBuilder();

        if (countNum > G) {
            long num = countNum / G;
            countNum -= num * G;
            sb.append(num).append("g");
            if ("g".equals(step)) {
                return sb.toString();
            }
        }
        if (countNum > M) {
            long num = countNum / M;
            countNum -= num * M;
            sb.append(num).append("m");
            if ("m".equals(step)) {
                return sb.toString();
            }
        }
        if (countNum > K) {
            long num = countNum / K;
            countNum -= num * K;
            sb.append(num).append("k");
            if ("k".equals(step)) {
                return sb.toString();
            }
        }
        sb.append(countNum);
        return sb.toString();
    }

    /**
     * 美化文件大小显示（对应 pretty_size）
     * @param size 原始大小（字节）
     * @return 美化后的大小字符串
     */
    public static String prettySize(long size) {
        final long G = 1024L * 1024 * 1024;
        final long M = 1024L * 1024;
        final long K = 1024L;

        StringBuilder sb = new StringBuilder();
        int collected = 0;

        // 处理 GB
        long d = size / G;
        if (d != 0 && collected < 2) {
            sb.append(d).append("GB");
            collected++;
            size -= d * G;
        }
        // 处理 MB
        d = size / M;
        if (d != 0 && collected < 2) {
            if (sb.length() > 0) sb.append(" ");
            sb.append(d).append("MB");
            collected++;
            size -= d * M;
        }
        // 处理 KB
        d = size / K;
        if (d != 0 && collected < 2) {
            if (sb.length() > 0) sb.append(" ");
            sb.append(d).append("KB");
            collected++;
            size -= d * K;
        }
        // 处理 B
        if (size != 0 && collected < 2) {
            if (sb.length() > 0) sb.append(" ");
            sb.append(size).append("B");
        }

        return sb.toString();
    }

    // ======================== 独立函数 ========================
    /**
     * 格式化字节大小（对应 formatBytes）
     * @param bytes 字节数
     * @param decimals 保留小数位数
     * @return 格式化后的字符串
     */
    public static String formatBytes(long bytes, int decimals) {
        if (bytes == 0) {
            return "0 Bytes";
        }
        final long k = 1024;
        final String[] sizes = {"Bytes", "KB", "MB", "GB", "TB", "PB", "EB", "ZB", "YB"};

        int i = (int) Math.floor(Math.log(bytes) / Math.log(k));
        double formatted = bytes / Math.pow(k, i);

        // 格式化小数
        DecimalFormat df = new DecimalFormat();
        df.setMaximumFractionDigits(decimals);
        df.setMinimumFractionDigits(decimals);
        return df.format(formatted) + " " + sizes[i];
    }

    /**
     * 重载：使用默认保留2位小数
     */
    public static String formatBytes(long bytes) {
        return formatBytes(bytes, 2);
    }

    /**
     * 美化秒数显示（对应 beautifySeconds）
     * @param seconds 总秒数
     * @return 格式化后的时间字符串（HH:mm:ss 或 mm:ss）
     */
    /**
     * 美化秒数显示，格式化为 HH:mm:ss 或 mm:ss（小于1小时时）
     * @param seconds 总秒数（需为非负整数，若传入负数会按0处理）
     * @return 格式化后的时间字符串
     */
    public static String beautifySeconds(long seconds) {
        // 处理负数情况，确保计算基准为非负
        seconds = Math.max(seconds, 0);
        
        // 计算小时、剩余分钟和最终剩余秒数（向下取整，Java整数除法默认向下取整）
        long hours = seconds / 3600;
        seconds %= 3600;
        long minutes = seconds / 60;
        seconds %= 60;

        // 格式化输出：数字小于10时补零，使用 String.format 简化补零逻辑
        if (hours > 0) {
            // 有小时数，格式化为 HH:mm:ss
            return String.format("%02d:%02d:%02d", hours, minutes, seconds);
        } else {
            // 无小时数，格式化为 mm:ss
            return String.format("%02d:%02d", minutes, seconds);
        }
    }

    /**
     * 计算字符串的 UTF-8 字节长度（对应 getUTF8ByteLength）
     * @param str 目标字符串
     * @return UTF-8 编码下的字节长度
     */
    public static int getUTF8ByteLength(String str) {
        if (str == null || str.isEmpty()) {
            return 0;
        }
        // Java 中直接获取 UTF-8 字节数组长度，效率更高且准确
        return str.getBytes(StandardCharsets.UTF_8).length;
    }
}
